/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufg.inf.si.poo.formula1.Race;

import br.ufg.inf.si.poo.formula1.Circuit.Circuit;
import br.ufg.inf.si.poo.formula1.Driver.Driver;

/**
 * Race
 * 
 * Versao 1.0
 * 
 * Data 21/01/2013
 * 
 * @author Igor
 */
public class Race {
    //Atributos
    private Driver[] drivers;
    private int qttDrivers;
    private Circuit circuit;
    private int year;
    private GridRace gridRace;
    private Qualification qualification;
    private int status;  //valores possível para Status estao no metodo validadeStatus

    //Construtores
    public Race(){}

    public Race(Circuit circuit, int year){
        this.drivers = new Driver[26];
        this.qttDrivers = 0;
        this.circuit = circuit;
        this.year = year;
        this.gridRace = new GridRace();
        this.qualification = new Qualification();
        this.status = 0; //Padronizo que a corrida nao aconteceu
    }

    //Metodos Getters and Setters
    /**
     * Retorna o atributo drivers (vetor de pilotos participantes da corrida)
     * @return o atributo drivers
     */
    public Driver[] getDrivers() {
        return drivers;
    }

    /**
     * Altera o atributo drivers (adiciona piloto a piloto na corrida)
     * @param o atributo drivers
     * @throws IllegalArgumentException
     */
    public void setDrivers(Driver drivers) throws IllegalArgumentException {
        int j = 0;
        if(this.qttDrivers < 26){
            if(drivers != null){
                if(validateTeam(drivers) < 2){
                    this.drivers[this.qttDrivers] = drivers;
                    this.qttDrivers++;
                }else{
                    throw new IllegalArgumentException("A equipe"+drivers.getTeam().getShortName()+" já possui dois pilotos na corrida.");
                }
            }
        }
    }

    /**
     * Retorna o atributo qttDrivers (quantidade de pilotos na corrida)
     * @return o atributo qttDrivers
     */
    public int getQttDrivers() {
        return qttDrivers;
    }

    /**
     * Altera o atributo qttDrivers (quantidade de pilotos na corrida)
     * @param o atributo qttDrivers
     */
    public void setQttDrivers(int qttDrivers) {
        this.qttDrivers = qttDrivers;
    }

    /**
     * Retorna o atributo circuit (objeto circuit, referente aa pista em que acontece a corrida)
     * @return o atributo circuit
     */
    public Circuit getCircuit() {
        return circuit;
    }

    /**
     * Altera o atributo circuit (objeto circuit, referente aa pista em que acontece a corrida)
     * @param o atributo circuit
     */
    public void setCircuit(Circuit circuit) {
        this.circuit = circuit;
    }

    /**
     * Retorna o atributo year (ano em que acontece a corrida)
     * @return o atributo year
     */
    public int getYear() {
        return year;
    }

    /**
     * Altera o atributo year (ano em que acontece a corrida)
     * @param o atributo year
     */
    public void setYear(int year) {
        this.year = year;
    }

    /**
     * Retorna o atributo gridRace (vetor do grid da corrida)
     * @return o atributo gridRace
     */
    public GridRace getGridRace() {
        return gridRace;
    }

    /**
     * Preenche qualification com todos os pilotos da corrida
     */
    public void setGridRace(Qualification qualification) {
        for(int i = 0;i < qualification.getQttDrivers();i++){
            this.gridRace.setGridRace(qualification.getQualification()[i]);
            if(i == 0){
                this.gridRace.getGridRace()[i].getDriver().getTeam().setPolePositions(this.gridRace.getGridRace()[i].getDriver().getTeam().getPolePositions() + 1);
            }
        }
    }

    /**
     * Preenche qualification com todos os pilotos da corrida
     * @param gridRace gridRace a ser preenchido
     */
    public void setGridRace(GridRace gridRace) {
        this.gridRace = gridRace;
    }

    /**
     * Retorna o atributo qualification (vetor da qualificacao)
     * @return o atributo qualification
     */
    public Qualification getQualification() {
        return qualification;
    }

    /**
     * Preenche qualification com todos os pilotos da corrida
     */
    public void setQualification() {
        for(int i = 0;i < qttDrivers;i++){

            GridPosition qualific = new GridPosition(
                    i+1, //O número do piloto sera o seu indici no vetor + 1 pois o indice comeca de 0
                    this.drivers[i],
                    this.circuit.getNumberLaps());

            this.qualification.setQualification(qualific);
        }
    }
    
    /**
     * Preenche qualification com todos os pilotos da corrida
     * @param qualification qualificacao a ser preenchida
     */
    public void setQualification(Qualification qualification) {
        this.qualification = qualification;
    }

    /**
     * Retorna o atributo status (valida se a corrida aconteceu normalmente ou nao e pq)
     * @return o atributo Status
     */
    public int getStatus() {
        return status;
    }

    /**
     * Altera o atributo status (valida se a corrida aconteceu normalmente ou nao e pq)
     * Valores possiveis
     * 0: corrida ainda nao aconteceu
     * 1: corrida nao aconteceu por falta de piloto
     * 2: corrida aconteceu sem problemas
     * 3: pilotos ja foram vinculados, qualificacao ja pode acontecer
     * 4: qualificacao ocorreu, corrida ja pode acontecer
     * @param status atributo Status
     */
    public void setStatus(int status) {
        this.status = status;
    }
    
    //Outros Metodos
    /**
     * Retorna o relatório da qualificação
     * @return 
     */
    public String printQualification(){
        String data = "";
        
        if(this.status != 1){
            data += this.year + " Formula 1 " + this.circuit.getCountry() + " Grand Prix\t\t\t\t\t\t\t\t" + this.circuit.getRaceDate() + "\n";
            data += "___________________________________________________________________________________________________________\n";
            data += this.qualification.toString() + "\n";
        }else if(this.status == 1){
            data += "A corrida nao aconteceu devido a falta de pilotos.\n";
        }
        
        return data;
    }

    /**
     * Retorna o relatório do grid da corrida
     */
    public String printGridRace(){
        String data = "";
        
        if(this.status != 1){
            data += this.year + " Formula 1 " + this.circuit.getCountry() + " Grand Prix\t\t\t\t\t" + this.circuit.getRaceDate() + "\n";
            data += "___________________________________________________________________________________\n";
            data += this.gridRace.toString() + "\n";
        }else if(this.status == 1){
            data += "A corrida nao aconteceu devido a falta de pilotos.\n";
        }
        
        return data;
    }

    /**
     * Valida se ja existem dois pilotos da mesma equipe
     * @param driver
     * @return 
     */
    public int validateTeam(Driver driver){
        int qttTeamInRace = 0;
        for(int i = 0;i < this.qttDrivers;i++){
            if(driver.getTeam().equals(this.drivers[i].getTeam())){
                qttTeamInRace++;
            }
        }
        return qttTeamInRace;
    }

    /**
     * Valida o status da corrida de acordo com a acao passada em execucao, ex.:
     * se quiser executar a qualificacao (execucao = 3) e a corrida estiver finalizada (status = 2)
     * entao sera gerado uma excecao
     * @param execucao
     * @throws IllegalArgumentException 
     */
    public void validateStatus(int execucao) throws IllegalArgumentException{
        /* Valores para 'execucao'
         * 1: viculando pilotos
         * 2: executando corrida
         * 3: executando qualificacao
         */
        switch(this.status){
            case 0: //0 = corrida ainda nao aconteceu
                if(execucao == 3 || execucao == 2){
                    throw new IllegalArgumentException("A corrida não está pronta. Vincule os pilotos.");
                }
                break;

            case 1: //1 = corrida nao aconteceu por falta de piloto
                throw new IllegalArgumentException("A corrida não foi realizada devido à falta de pilotos.");

            case 2: //2 = corrida aconteceu sem problemas
                if(execucao == 1 || execucao == 2 || execucao == 3){
                    throw new IllegalArgumentException("Corrida já foi realizada.");
                }
                break;

            case 3: //3 = pilotos ja foram vinculados, qualificacao ja pode acontecer
                if(execucao == 1){
                    throw new IllegalArgumentException("Pilotos já foram vinculados");
                } else if (execucao == 2){
                    throw new IllegalArgumentException("Impossível realizar corrida! A Qualificação não foi realizada.");
                }
                break;

            case 4: //4 = qualificacao ocorreu, corrida ja pode acontecer
                if(execucao == 1){
                    throw new IllegalArgumentException("Impossível vincular Pilotos, pois a Qualificacao já foi realizada.");
                }else if(execucao == 3){
                    throw new IllegalArgumentException("A Qualificação já foi realizada.");
                }
                break;
        }
    }
}